#pragma once

#include <iostream>
#include <string>
#include <list>
#include <memory>
#include <algorithm>
#include <sys/types.h>
#include <sys/socket.h>

#include "Inet_host.hpp"
#include "Logger.hpp"
#include "Mutex.hpp"

using namespace LogMudule;
using namespace LockModule;


class UserInterface
{
public:
    virtual void SendTo(int sockfd, const std::string &message) = 0;
    virtual bool operator==(const InetAddr &u) = 0;
    virtual ~UserInterface() = default;
    virtual std::string Id() = 0;
};

class User : public UserInterface
{
public:
    User(InetAddr addr)
        : _addr(addr)
    {
    }
    void SendTo(int sockfd, const std::string &message) override
    {
        LOG(LogLevel::INFO) << "Sendto message " << _addr.Addr();
        int n = ::sendto(sockfd, message.c_str(), sizeof(message), 0, _addr.SockAddr(), _addr.SockLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << strerror(SENDTO_ERR);
            Die(SENDTO_ERR);
        }
    }
    bool operator==(const InetAddr &u) override
    {
        return _addr == u;
    }
    std::string Id() override
    {
        return _addr.Addr();
    }
    ~User()
    {
    }

private:
    InetAddr _addr;
};

class UserManager
{
public:
    UserManager()
    {
    }
    void AddUser(InetAddr &id)
    {
        LockGuard lockguard(_mutex);
        for (auto &u : _ums)
        {
            if (*u == id)
            {
                LOG(LogLevel::INFO) << "用户已存在";
                return;
            }
        }
        LOG(LogLevel::INFO) << "添加新用户" << id.Addr();
        _ums.push_back(std::make_shared<User>(id));
        PrintUser();
    }
    void DelUser(InetAddr &id)
    {
        LockGuard lockguard(_mutex);
        auto pos = std::remove_if(_ums.begin(), _ums.end(), [&id](std::shared_ptr<UserInterface> &user)
                                  { return *user == id; });
        _ums.erase(pos, _ums.end());
    }
    void Route(int sockfd, const std::string &message)
    {
        LockGuard lockguard(_mutex);
        for (auto &u : _ums)
        {
            u->SendTo(sockfd, message);
        }
    }
    void PrintUser()
    {
        for (auto &user : _ums)
        {
            LOG(LogLevel::DEBUG) << "在线用户-> " << user->Id();
        }
    }
    ~UserManager()
    {
    }

private:
    std::list<std::shared_ptr<UserInterface>> _ums;
    Mutex _mutex;
};